home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
program
/
tjgold.zip
/
INSTALL.001
/
GOLD.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-05-29
|
40KB
|
1,724 lines
; Copyright 1995 TJ Software
; All Rights Reserved
; Restricted by License
; Version 1.0
; ***** GOLD.ASM *****
; Assembly procedures for TTT Gold
; A collaborative effort by Charley Martin and Bob "Torqemada" Ainsbury
;-------- PROGRAM DATA STRUCTURES ---------
; WinList Structure: Doubly-linked structure of Window parms:
; Parm Offset Type Definition
; Buffer 0 Dword Points to Window data
; Width 4 Byte Window width
; Depth 5 Byte Window depth
; X 6 Byte X coord of Window on Screen plane
; Y 7 Byte Y coord of Window on Screen plane
; NextEntry 8 Dword Pointer to next structure (NULL if this is last)
; .
; .
; .
; Equates for WinWrite, WinPlain:
WWIgnore EQU BYTE PTR [BP+6] ;Ignore ShowNow
WWStr EQU DWORD PTR [BP+8] ;Reset by 2
WWStrSeg EQU WORD PTR [BP+10]
WWAttr EQU BYTE PTR [BP+12]
WWY3 EQU BYTE PTR [BP+14]
WWX3 EQU BYTE PTR [BP+16]
WWY2 EQU BYTE PTR [BP+18]
WWX2 EQU BYTE PTR [BP+20]
WWY1 EQU BYTE PTR [BP+22]
WWX1 EQU BYTE PTR [BP+24]
WWWidth EQU BYTE PTR [BP+26]
WWBuffer EQU DWORD PTR [BP+28]
WWBuffOff EQU WORD PTR [BP+28] ;Assumes segment gets pushed first
WWBuffSeg EQU WORD PTR [BP+30]
WWAdjust EQU 26 ;Stack adjustment on return from WinWrite, WinPlain
; Equates for WinAttr:
WAIgnore EQU BYTE PTR [BP+6] ;Ignore ShowNow
WAAttr EQU BYTE PTR [BP+8] ;All adjusted by 2
WAY4 EQU BYTE PTR [BP+10]
WAX4 EQU BYTE PTR [BP+12]
WAY3 EQU BYTE PTR [BP+14]
WAX3 EQU BYTE PTR [BP+16] ;X3,Y3 and X4,Y4 define pane in area, relative
WAY2 EQU BYTE PTR [BP+18] ;to edges of area
WAX2 EQU BYTE PTR [BP+20]
WAY1 EQU BYTE PTR [BP+22]
WAX1 EQU BYTE PTR [BP+24] ;X1,Y1 and X2,Y2 define area within window,
WAWidth EQU BYTE PTR [BP+26] ;relative to window edges
WABuffer EQU DWORD PTR [BP+28]
WABuffOff EQU WORD PTR [BP+28]
WABuffSeg EQU WORD PTR [BP+30]
WAAdjust EQU 26 ;Stack adjustment
; Equates for FillVideo:
FVData EQU WORD PTR [BP+6]
FVLen EQU WORD PTR [BP+8]
FVBuffer EQU DWORD PTR [BP+10]
FVAdjust EQU 8 ;Stack adjustment
; Equates for WinRedraw:
WRShow EQU BYTE PTR [BP+6]
WRAdjust EQU 2
; Equates for MoveFromScreen
MFTarget EQU DWORD PTR [BP+6]
MFSource EQU DWORD PTR [BP+10] ;Added 7/7/93 on request
MFSourceOff EQU WORD PTR [BP+10] ;Extra definition
MFSourceSeg EQU WORD PTR [BP+12] ; "
MFSWidth EQU BYTE PTR [BP+14] ;Added 7/7/93
MFY2 EQU BYTE PTR [BP+16]
MFX2 EQU BYTE PTR [BP+18]
MFY1 EQU BYTE PTR [BP+20]
MFX1 EQU BYTE PTR [BP+22]
MFAdjust EQU 18 ;Stack adjustment on far return
; Equates for MoveToScreen
MTTarget EQU DWORD PTR [BP+6] ;pointer to target buffer
MTTargetOff EQU WORD PTR [BP+6] ;Extra
MTTargetSeg EQU WORD PTR [BP+8] ;Extra
MTTWidth EQU BYTE PTR [BP+10] ;width of target screen
MTTY3 EQU BYTE PTR [BP+12] ;upper-left corner of target
MTTX3 EQU BYTE PTR [BP+14] ;upper-left corner of target
MTSource EQU DWORD PTR [BP+16];pointer to source buffer
MTSourceOff EQU WORD PTR [BP+16] ;Extra
MTSourceSeg EQU WORD PTR [BP+18] ;Extra
MTSWidth EQU BYTE PTR [BP+20] ;width of source screen
MTSY2 EQU BYTE PTR [BP+22] ;lower-rght corner of source
MTSX2 EQU BYTE PTR [BP+24] ;lower-rght corner of source
MTSY1 EQU BYTE PTR [BP+26] ;upper-left corner of source
MTSX1 EQU BYTE PTR [BP+28] ;upper-left corner of source
MTAdjust EQU 24 ;Stack adjustment on far return
; Equates for Different
MCSource EQU DWORD PTR [BP+6] ;pointer to source buffer
MCTarget EQU DWORD PTR [BP+10] ;pointer to target buffer
MCByteCount EQU WORD PTR [BP+14] ;number of bytes to compare
MCByteCount EQU WORD PTR [BP+6] ;number of bytes to compare
MCTarget EQU DWORD PTR [BP+8] ;pointer to target buffer
MCSource EQU DWORD PTR [BP+12] ;pointer to source buffer
MCAdjust EQU 10
; ------------ GLOBAL DATA ----------------
SEGMENT DATA byte public
EXTRN SnowProne : BYTE
EXTRN LineWrap : BYTE
EXTRN ShowNow : BYTE
EXTRN ScreenLines : BYTE
EXTRN WinList : DWORD
EXTRN BackBuffer : DWORD
EXTRN FrontBuffer : DWORD ;Pointer to Video work area
; ***** THESE DECLARATIONS MUST BE ADDED TO THE DATA AREA *****
EXTRN WinX : BYTE
EXTRN WinY : BYTE
EXTRN WinWidth0 : WORD
EXTRN WinWidth : WORD
EXTRN WinDepth0 : WORD
EXTRN WinDepth : WORD
EXTRN WinOff : WORD
EXTRN SourceIncr : WORD
EXTRN TargetIncr : WORD
EXTRN ShadowAttr : BYTE
EXTRN ShadowType : BYTE ;4=no shadow
EXTRN PaneType : BYTE
EXTRN CRFlag : BYTE
EXTRN PaneWidth : WORD
EXTRN PaneDepth : WORD
EXTRN PaneOff : WORD
EXTRN WriteDepth : BYTE
EXTRN SegB000 : WORD
EXTRN SegB800 : WORD
EXTRN BBTop : BYTE
EXTRN BBBot : BYTE
ENDS DATA
SEGMENT CODE byte public
ASSUME CS:CODE, DS:DATA
PUBLIC WinWrite, WinPlain, WinAttr, WinRedraw, FillVideo, TopWinRedraw
PUBLIC MoveToScreen, MoveFromScreen, Different, A@@@@@@@@@
;-------- PROGRAM CODE AREA --------
;------------------
MoveFromScreen proc far
; MoveFromScreen moves part of the screen (character and attr)
; from the visible screen to a buffer. Target is a contiguous array
; Source far pointer and width are passed, and NOT assumed to be
; visible screen
cld
push bp ;Save base pointer
mov bp,sp ;Set up stack frame
mov al,MFSWidth ;Calculate Source increment
xor ah,ah
shl ax,1
mov [SourceIncr],ax
mov al,MFY1 ;calculate offset in video memory
dec al
mov bl,MFSWidth
mul bl
add al,MFX1
adc ah,0
dec ax
shl ax,1
mov si,ax
add si,MFSourceOff
mov cl,MFY2 ;How many rows? Hold in cx
sub cl,MFY1
inc cl
xor ch,ch
mov bl,MFX2 ;How many chars wide? Hold in bx
sub bl,MFX1
inc bl
xor bh,bh
les di,MFTarget
MFS_Loop:
push cx
push si
mov cx,bx
push ds
mov ds,MFSourceSeg
rep movsw
pop ds
pop si
pop cx
add si,[SourceIncr]
loop MFS_Loop
pop bp
ret MFAdjust
MoveFromScreen endp
;------------------
MoveToScreen proc far
; MoveToScreen moves part (or all) of a virtual screen to part of
; another virtual screen, or the visible screen. If the target is the
; visible screen, snow checking should be performed.
; No checking is done for negative values of coords
cld
push bp ;Save base pointer
mov bp,sp ;Set up stack frame
cmp [SnowProne],0
je MTS_0
call GetVidSeg
cmp dx,MTTargetSeg
jne MTS_0
call VerticalPause
MTS_0:
mov al,MTSWidth
xor ah,ah
shl ax,1
mov [SourceIncr],ax
mov al,MTTWidth
xor ah,ah
shl ax,1
mov [TargetIncr],ax
mov al,MTSY2
sub al,MTSY1
inc al
xor ah,ah
mov [PaneDepth],ax
mov al,MTSX2
sub al,MTSX1
inc al
xor ah,ah
mov [PaneWidth],ax
mov al,MTSY1
dec al
mov bl,MTSWidth
mul bl
add al,MTSX1
adc ah,0
dec ax
shl ax,1
mov si,ax
mov al,MTTY3
dec al
mov bl,MTTWidth
mul bl
add al,MTTX3
adc ah,0
dec ax
shl ax,1
mov di,ax
add si,MTSourceOff
add di,MTTargetOff
mov es,MTTargetSeg
mov cx,[PaneDepth]
MTS_loop:
push cx
push si
push di
mov cx,[PaneWidth]
push ds
mov ds,MTSourceSeg
rep movsw
pop ds
pop di
pop si
pop cx
add si,[SourceIncr]
add di,[TargetIncr]
loop MTS_loop
pop bp
ret MTAdjust
MoveToScreen endp
;------------------
WinWrite proc far
; Passes cursor coords back through ax -- see PaneWrite
cld
push bp ;Save base pointer
mov bp,sp ;Set up stack frame _before_ PaneWrite call
call CheckRange
jnc win_write_0
pop bp
ret WWAdjust
win_write_0:
call GetVidSeg
cmp WWBuffSeg,dx
jne winw_begin
cmp [SnowProne],0
je winw_begin
call VerticalPause
winw_begin:
mov al,-1
call PaneWrite ;restores ds on return
cmp [ShowNow],0
je winw_leave
cmp WWIgnore,0 ;WWIgnore overrides ShowNow
ja winw_leave
call GetVidSeg
cmp WWBuffSeg,dx
je winw_leave
cmp [SnowProne],0
je winw_put
call VerticalPause
winw_put:
call TopWinDrawLocal
winw_leave:
pop bp
ret WWAdjust
WinWrite endp
;------------------
WinPlain proc far
; Passes cursor coords back through ax -- see PaneWrite
cld
push bp ;Save base pointer
mov bp,sp ;Set up stack frame _before_ PaneWrite call
call CheckRange
jnc win_plain_0
pop bp
ret WWAdjust
win_plain_0:
call GetVidSeg
cmp WWBuffSeg,dx
jne winp_begin
cmp [SnowProne],0
je winp_begin
call VerticalPause
winp_begin:
mov al,0
call PaneWrite
cmp [ShowNow],0
je winp_leave
cmp WWIgnore,0 ;WWIgnore overrides ShowNow
ja winp_leave
call GetVidSeg
cmp WWBuffSeg,dx
je winp_leave
cmp [SnowProne],0
je winp_put
call VerticalPause
winp_put:
call TopWinDrawLocal
winp_leave:
pop bp
ret WWAdjust
WinPlain endp
;------------------
WinAttr proc far
; Paints attribute of whole Pane based on passed parms
; Entry: None -- BP set up for the EQU references
; Return: None
; (Following code duplicated from PaneWrite, recast to WA equates)
; Calculate local parameters for the Pane -- Width and depth
cld
push bp ;Save base pointer
mov bp,sp ;Set up stack frame
mov al,WAX4 ;Calc pane width
sub al,WAX3
inc al ;Width is one more than the difference in coords
jns wa_1 ;test: negative pane width
jmp wa_out
wa_1:
cbw
mov [PaneWidth],ax ;Word-width, _not_ Byte-width!
mov al,WAY4
sub al,WAY3
inc al
jns wa_2 ;test: negative pane depth
jmp wa_out
wa_2:
cbw
mov [PaneDepth],ax
; Calculate a pointer to the Pane
mov ax,WABuffOff
mov [PaneOff],ax ;(not the final value)
mov al,WAWidth ;Assume this is the Word-width of Window
xor ah,ah
shl ax,1 ;Double to get Byte-width
mov [TargetIncr],ax ;Pane line separation in Window buffer
mov bl,WAY1
dec bl ;X and Y are 1-based
add bl,WAY3
dec bl ;X and Y are 1-based
jns wa_3 ;test: is Y negative?
jmp wa_out
wa_3:
mov dl,al ;test: is the pane within the window?
add dl,byte ptr [PaneDepth]
cmp dl,WAY2
jg wa_out
mul bl
add [PaneOff],ax ;Increment due to rows below top of Window
mov al,WAX1
dec al ;Since 1-based
add al,WAX3
dec al
js wa_out ;test: is X negative?
mov dl,al ;test: is the pane within the window
add dl,byte ptr [PaneWidth]
cmp dl,WAWidth
jg wa_out
cbw
shl ax,1 ;To get Byte-width
add [PaneOff],ax ;WABuffSeg:PaneOff now points to Pane top left
; Paint the Pane
mov es,WABuffSeg
mov di,[PaneOff]
mov cx,[PaneDepth] ;Outer loop on number of lines
call GetVidSeg ;Are we repainting the video directly?
mov ax,es
cmp dx,ax
jne wa_direct
call VerticalPause
wa_direct:
mov al,WAAttr ;color to paint
wa_loop1:
push cx
push di
mov cx,[PaneWidth] ;Inner loop on each line
wa_loop2:
inc di ;position on attribute byte
stosb ;store the new attr
loop wa_loop2
pop di
add di,[TargetIncr]
pop cx
loop wa_loop1
cmp [ShowNow],0
je wa_out
cmp WAIgnore,0 ;If WAIgnore set, also override ShowNow
ja wa_out
call GetVidSeg ;Did we repaint the video directly?
mov ax,es
cmp dx,ax
je wa_out
cmp [SnowProne],0
je wa_put
call VerticalPause
wa_put:
call TopWinDrawLocal
wa_out:
pop bp
ret WAAdjust ;Adjust for parms list
WinAttr endp
;------------------
WinRedraw proc far
; Transfers image of BackBuffer to video work area
; Draws all the Windows in the WinList structure to video work area
; Transfers video work area to active video page
cld
push bp ;Save base pointer
mov bp,sp ;Set up stack frame
mov ax,word ptr [WinList+2] ;Segment of WinList
cmp ax,0
je WR_exit
call WinDrawLocal
WR_exit:
pop bp
ret WRAdjust
WinRedraw endp
;------------------
TopWinRedraw proc far
; Refreshes the top window to screen, only
; Assumes no change in top window's dimensions
cld
mov ax,word ptr [WinList+2] ;Segment of WinList
cmp ax,0
je TWR_exit
call TopWinDrawLocal
TWR_exit:
ret
TopWinRedraw endp
;------------------
CheckRange proc near
; Checks range of variables passed to WinWrite and WinPlain
cmp WWX1,0
jg ChkRange1
stc
ret
ChkRange1:
cmp WWY1,0
jg ChkRange2
stc
ret
ChkRange2:
mov al,WWY2 ;is depth >0
sub al,WWY1
inc al
jns ChkRange3
stc
ret
ChkRange3:
cmp al,WWY3 ;is start of write in range?
jge ChkRange4
stc
ret
ChkRange4:
mov al,WWX2
cmp al,WWWidth ;is right side of pane in window?
jle ChkRange5
stc
ret
ChkRange5:
sub al,WWX1
inc al
jns ChkRange6
stc
ret
ChkRange6:
cmp al,WWX3
jge ChkRange7
stc
ret
ChkRange7:
clc
ret
CheckRange endp
;------------------
TopWinDrawLocal proc near
; Near proc for drawing the top window
cld
les bx,[WinList] ;load far pointer to top window structure
mov ax,es
and ax,-1
jz twd_exit ;make sure not zero
twd_0:
cmp word ptr es:[bx+10],0 ;segment of next pointer
je twd_1
les bx,es:[bx+8]
jmp twd_0
twd_1:
call PutWin
mov dx,word ptr [FrontBuffer+2] ;New code - 1/29/94 - restore menu/status lines
mov ax,word ptr [FrontBuffer]
call RestoreTopBot
call PutScreen
twd_exit:
ret
TopWinDrawLocal endp
;------------------
WinDrawLocal proc near
cld
call PutBackBuffer
les bx,[WinList] ;load far pointer to first window structure
wd_start:
mov ax,es ;Is pointer NULL
and ax,-1
jz wd_exit ;WinList pointed to NULL entry
call PutWin
les bx,es:[bx+8] ;Load the back-pointer
jmp wd_start
wd_exit:
mov dx,word ptr [FrontBuffer+2] ;New code - 1/29/94 - restore menu/status lines
mov ax,word ptr [FrontBuffer]
call RestoreTopBot
cmp WRShow,0 ;If ignore set, bypass screen put
je wd_out
call PutScreen
wd_out:
ret
WinDrawLocal endp
;------------------
PutWin proc near
; Puts the window whose structure is pointed to by es:bx
; Adjust width and depth to keep from overrunning screen edge
cld
mov dl,es:[bx+6] ;X coord of window, 1-based for consistency
cmp dl,81
jl pwinx
jmp pwin_next
pwinx:
mov [WinX],dl
mov al,es:[bx+4] ;window width
xor ah,ah
mov [WinWidth0],ax ;Before truncation
shl ax,1
mov [SourceIncr],ax ;how much to increment the source
shr ax,1 ;index on each row
add dl,al ;see if goes beyond right edge
sub dl,81 ;Screen width plus 1, since 1-based
js pwin_sto_wid ;if sign, <screen width
sub al,dl
pwin_sto_wid:
mov dl,[WinX]
dec dl
jns pwin_sto_wid1
add al,dl ;add the negative X coord to the width
mov [WinX],1
pwin_sto_wid1:
cmp al,0
jg pwin_sto_wid2
jmp pwin_next
pwin_sto_wid2:
xor ah,ah
mov [WinWidth],ax ;possibly truncated
mov dl,es:[bx+7] ;Y coord of window, 1-based
mov [WinY],dl
cmp dl,[ScreenLines]
jle pwiny
jmp pwin_next
pwiny:
mov al,es:[bx+5] ;window depth
xor ah,ah
mov [WinDepth0],ax ;before truncation
add dl,al
sub dl,[ScreenLines]
dec dl ;since 1-based
js pwin_sto_dep
sub al,dl
pwin_sto_dep:
mov dl,[WinY]
dec dl
jns pwin_sto_dep1
add al,dl ;add the negative Y coord to the depth
mov [WinY],1
pwin_sto_dep1:
cmp al,0
jg pwin_sto_dep2
jmp pwin_next
pwin_sto_dep2:
xor ah,ah
mov [WinDepth],ax
; Calculate starting point in video work area for this window
mov al,[winY] ;Y coord of window -- assume 1-based for consistency
dec al
push bx ;save offset to window structure
mov bl,160 ;bytes per video screen line
mul bl
pop bx
mov dx,ax
mov al,[WinX] ;X coord -- also assume 1-based
xor ah,ah
dec ax
shl ax,1 ;since 2 bytes per position
add ax,dx ;ax now has offset in video work area for this Window
mov di,ax
mov [WinOff],ax
add di,word ptr [FrontBuffer] ;video work area
mov al,es:[bx+7] ;Y coord -- Adjust pointer to source if needed
dec al
js pw_adj_source
xor al,al
pw_adj_source:
not al
inc al
push bx
mov bl,byte ptr [WinWidth0]
mul bl
pop bx
mov dl,es:[bx+6] ;X coord
dec dl
js pw_adj_source1
xor dl,dl
pw_adj_source1:
not dl
inc dl
xor dh,dh
add ax,dx
shl ax,1
push bx ;save far pointer to structure
push es
les si,es:[bx] ;load the far pointer to the window data area -- source set
add si,ax
mov cx,[WinDepth] ;for outer loop
pwin_loop:
push cx ;save line counter
push di ;save destination index
push si ;save source
mov cx,[WinWidth]
pwin_1:
push ds
push es
mov es,word ptr [FrontBuffer+2]
pop ds
rep movsw
push ds
pop es
pop ds
pop si
add si,[SourceIncr] ;next source window line
pop di
add di,160 ;next screen line
pop cx
loop pwin_loop
; Paint the shadows:
pop es ;retrieve pointer to structure
pop bx
push bx
push es
mov al,es:[bx+6] ;Shading rutines want original versions of X,Y
mov [WinX],al
mov al,es:[bx+7]
mov [WinY],al
call ShadeVert
call ShadeHoriz
pop es ;retrieve pointer to structure
pop bx
pwin_next: ;get pointer to next structure
ret
PutWin endp
;------------------
ShadeVert proc near
; Shades the vertical lines in the shadow
test [ShadowType],4 ;is this unshadowed (ie, =4)?
jz sv_0
ret
; Calculate coords of shading
sv_0:
cld
mov al,[WinY]
test [ShadowType],2 ;top or bottom shadow?
jz sv_1
inc al
jmp sv_2
sv_1:
dec al
sv_2:
mov dl,[WinX]
test [ShadowType],1 ;left or right shadow?
jz sv_3
add dl,byte ptr [WinWidth0]
jmp sv_4
sv_3:
dec dl
dec dl
sv_4:
; al now has shadow Y, dl shadow X
; Calculate offset of shadow
push ax
push dx
dec al ;because Y 1-based
cbw
mov bx,80
push dx
mul bx
pop dx
xchg ax,dx
cbw
add ax,dx
dec ax ;because X 1-based
shl ax,1
inc ax
mov di,ax ;di now has offset of attr for vertical shading
add di,word ptr [FrontBuffer] ;video work area
mov es,word ptr [FrontBuffer+2]
pop dx
pop ax ;al has shadow Y - stack right
mov dh,al ;X is in dl, and Y is in dh
mov bl,80 ;XMax
mov bh,[ScreenLines] ;YMax
mov cx,[WinDepth0]
mov al,[ShadowAttr]
cmp dl,1 ;Is X coord of shading in bounds?
jl sv_6
cmp dl,bl
jg sv_6
sv_5:
push cx
push dx
push di
sv_left_loop:
cmp dh,1 ;Is Y coord in bounds?
jl sv_left_loop1
cmp dh,bh
jg sv_left_loop1
stosb
jmp sv_left_loop2
sv_left_loop1: ;bypass the attr stosb
inc di
sv_left_loop2:
add di,159 ;position to next row
inc dh ;adjust dummy Y to next row
loop sv_left_loop
pop di ;Restore dest index...
pop dx ;coords...
pop cx ;and counter - stack right
sv_6:
inc dl ;index X to next column
inc di ;adjust dest ptr
inc di
cmp dl,1 ;Is X coord of shading in bounds?
jl sv_out
cmp dl,bl
jg sv_out
sv_rt_loop:
cmp dh,1 ;Is Y coord in bounds?
jl sv_rt_loop1
cmp dh,bh
jg sv_rt_loop1
stosb
jmp sv_rt_loop2
sv_rt_loop1: ;bypass the attr stosb
inc di
sv_rt_loop2:
add di,159 ;position to next row
inc dh ;increment dummy y
loop sv_rt_loop
sv_out:
ret
ShadeVert endp
;------------------
ShadeHoriz proc near
; Shades the horizontal line in the shadow
test [ShadowType],4 ;is this unshadowed (ie, =4)?
jz sh_0
ret
; Calculate coords of horizontal shading
sh_0:
cld
mov al,[WinY]
test [ShadowType],2 ;top or bottom shadow?
jnz sh_1
dec al
jmp sh_2
sh_1:
add al,byte ptr [WinDepth0]
sh_2:
mov dl,[WinX]
test [ShadowType],1 ;left or right shadow?
jz sh_3
inc dl
inc dl
jmp sh_4
sh_3:
dec dl
dec dl
sh_4:
; al now has shadow Y, dl shadow X
; Calculate offset of shadow
push ax
push dx
dec al ;Since Y coord of shade is 1-based
cbw
mov bx,80
push dx
mul bx
pop dx
xchg ax,dx
cbw
add ax,dx
dec ax ;Since the X coord of shade is 1-based
shl ax,1
inc ax
mov di,ax ;di now has offset of attr for horizontal shading
add di,word ptr [FrontBuffer] ;video work area
mov es,word ptr [FrontBuffer+2]
pop dx
pop ax ;al has shadow Y - stack right
mov dh,al ;X is in dl and Y in dh
mov bl,80 ;XMax
mov bh,[ScreenLines] ;YMax
mov cx,[WinWidth0]
mov al,[ShadowAttr]
cmp dh,1 ;Is shadow Y in bounds
jl sh_out
cmp dh,bh
jg sh_out
sh_loop:
cmp dl,1 ;Is shadow X in bounds?
jl sh_loop1
cmp dl,bl
jg sh_loop1
stosb
jmp sh_loop2
sh_loop1:
inc di
sh_loop2:
inc di
inc dl ;adjust dummy X to next col
loop sh_loop
sh_out:
ret
ShadeHoriz endp
;------------------
PaneWrite proc near
; Writes data from far string into Window work area "pane" defined
; by WWX1,WWY1 - WWX2,XXY2, starting at WWX3, WWY3
; Entry: al= 0, call was from WinPlain
; =-1, call was from WinWrite
; Return: al=X coordinate of final cursor position relative to Pane top left
; ah=Y coordinate as above
; X,Y calculated for next position in the Pane beyond the written
; string, unless the right-hand edge of the pane was encountered
; and line wrapping was _not_ in effect, or string ended up dead
; against the lower right boundary of the Pane. In these cases
; the cursor coords point to the last character written.
cld
mov [PaneType],al ;store for attribute decisions
mov [CRFlag],0 ;Initialize carriage return flag
push ds
lds si,WWStr ;test for zero-length
lodsb ;length
pop ds
cmp al,0
jne pw_start
mov al,WWX3
mov ah,WWY3
ret
pw_start:
; Calculate local parameters for the Pane -- Width and depth
mov al,WWX2 ;Calc pane width
sub al,WWX1
inc al ;Width is one more than the difference in coords
xor ah,ah
mov [PaneWidth],ax ;Word-width, _not_ Byte-width!
mov al,WWY2
sub al,WWY1
inc al
xor ah,ah
mov [PaneDepth],ax
; Calculate a pointer to the Pane
mov ax,WWBuffOff
mov [PaneOff],ax ;(not the final value)
mov al,WWWidth ;Assume this is the Word-width of Window
shl al,1 ;Double to get Byte-width
xor ah,ah
mov [TargetIncr],ax ;Pane line separation in Window buffer
mov bl,WWY1
dec bl ;X and Y are 1-based
mul bl
add [PaneOff],ax ;Increment due to rows below top of Window
mov al,WWX1
dec al ;Since 1-based
shl al,1 ;To get Byte-width
xor ah,ah
add [PaneOff],ax ;WWBuffSeg:PaneOff now points to Pane top left
; Calculate destination pointer to start the write operation
mov es,WWBuffSeg ;es:di point to top-left of Pane
mov di,[PaneOff] ;how much to add to point to write start?
mov al,WWY3 ;1-based _local_ (relative to WWY1) coord to start write
dec al ;No adjustment if on row 1
mov bl,byte ptr [TargetIncr] ;Number of rows deep*line index for Window
mul bl
add di,ax ;Offset to left edge of Pane, on same line as write starts
push di ;Save this offset for subsequent lines -- Stack +1 --
mov dl,WWX3
dec dl ;Since also 1-based
shl dl,1 ;For Byte-offset
xor dh,dh
add di,dx ;ax contains incremental offset from Pane corner to write
;location
; How many lines can we write?
mov al,byte ptr [PaneDepth]
sub al,WWY3 ;al has number of lines in pane below starting line
mov [WriteDepth],al
; How many characters permitted on first line of write?
mov cl,byte ptr [PaneWidth] ;Word-wise width
xor ch,ch ;subsequent lines will use the full PaneWidth
push cx ;save counter for subsequent lines -- Stack +2 --
sub cl,WWX3
inc cl ;since X3 is 1-based -- no adjustment if on col 1
push ds
lds si,WWStr ;Load the string pointer
lodsb ;string length in al
pop ds
mov dl,al ;Keep separate track of string count in dl
mov ah,WWAttr
mov dh,[PaneType] ;dh has flag whether to store WWAttr with char
jmp pw_loop1 ;Bypass the pushes for the line width counter counter and
;destination index to Window Buffer,
;since di and cx on stack already
pw_loop:
push di
push cx
pw_loop1:
push ds
mov ds,WWStrSeg
lodsb ;next byte of string
pop ds
dec dl ;initial value of string len was _not_ zero
cmp al,13
je pw_fill_line
cmp al,10
jne pw_loop2 ;char is not delimiter. Print and keep looping
;--------- If Delimiter: --------
pw_fill_line: ;delimiter: Fill rest of line with blanks
mov al,32 ;blank
pw_fl_loop: ;fill rest of line with blanks
cmp dh,0
je pw_fl_no_attr
stosw
jmp pw_fl_loop_end
pw_fl_no_attr:
stosb
inc di
pw_fl_loop_end:
loop pw_fl_loop
mov cx,1 ;Reset line counter so loop will fall through
mov [CRFlag],-1 ;Set the flag that says encountered CR or LF
cmp dl,0 ;was LF or CR end of string?
je pw_scroll_out
push ds
mov ds,WWStrSeg
mov bx,[si+0FFFFh]
pop ds
cmp bx,0A0Dh ;Was the CR or LF followed by a LF or CR?
je pw_eat_crlf
cmp word ptr [si+0FFFFh],0D0Ah
jne pw_test2 ;loop out
pw_eat_crlf:
lodsb ;eat the next char
dec dl ;decrement string length counter
cmp dl,0 ;was the second delimiter the last char in string?
jne pw_test2 ;more in the string. Fall through loop and scroll
pw_scroll_out: ;line delimiter was last char of string...
pop cx
pop bx ;stack is right for exit
cmp [WriteDepth],0 ;is there a free line below this
ja pw_scroll_out1
cmp [LineWrap],0
je pw_exit ;if scroll off and no more lines below, leave di and exit
pw_scroll_out1:
mov di,bx
add di,[TargetIncr] ;Reindex the destination to next line down in window
dec [WriteDepth] ;last line in pane?
jns pw_exit ;No - Just exit
call ScrollPane ;Yes - Scroll pane and exit
jmp pw_exit
;----------------------------
pw_loop2: ;Came here is char was not delimiter
cmp dh,0
je pw_no_attr
stosw
jmp pw_test
pw_no_attr:
stosb
inc di ;in place of attribute
pw_test:
cmp dl,0
jne pw_test2 ;more chars in string. Fall through loop and scroll
pop cx ;End-of-string -- clear the stack...
pop bx ;Leave di alone for coordinate calculation
jmp pw_exit ;...and leave
pw_test2:
loop pw_loop1a ;loops to end of line in Pane
jmp short pw_loop1_out
pw_loop1a:
jmp pw_loop1
pw_loop1_out:
pop cx ;end of line in Pane -- this is line byte counter
pop bx ;stack is right. Leave di alone for possible coord calc
cmp [CRFlag],-1 ;If CRFlag set, overrides LineWrap off
je pw_test3
cmp [LineWrap],0 ;wrapping on?
jne pw_test3
cmp byte ptr [WriteDepth],0
je pw_exit ;if no line wrapping and no line below, done
mov di,bx ;if room below current line in pane, move to start of it
add di,[TargetIncr]
jmp pw_exit
pw_test3: ;wrapping is on, or CR or LF encountered
mov [CRFlag],0 ;reset carriage return flag
mov di,bx ;Restore di, since not exiting
add di,[TargetIncr] ;Reindex the destination to next line down in window
dec [WriteDepth]
js pw_scroll
jmp pw_loop
; Got to bottom of pane. That means long string, line wrapping is in effect
; Scroll the pane up a line, adjust di back to start of last line.
pw_scroll:
call ScrollPane ;It saves all key registers
sub di,[TargetIncr] ;restore destination index to bottm line of Pane
jmp pw_loop ;Keep doing this until string is finished
pw_exit: ;di has the next cursor position, byte-wise, rel to Window
mov ax,di
sub ax,[PaneOff] ;adjust to top left of Pane
mov bl,byte ptr [TargetIncr] ;find coords rel to Window top left
div bl ;al will have 0-based Y, ah 0-based X
xchg ah,al ;get them in the prescribed regs
sub al,WWX1 ;make rel to Pane top left
sub ah,WWY1
add ax,101h ;make them 1-based
cmp al,byte ptr [PaneWidth] ;is it past the right edge of pane?
jbe pw_exit2 ;if legal, exit
cmp [LineWrap],0 ;if wrap off, force to right edge of Pane
jne pw_exit3
mov al,byte ptr [PaneWidth] ;force to right edge of Pane
jmp pw_exit2
pw_exit3:
mov al,1 ;if past right edge, force to start of next line
inc ah
cmp ah,byte ptr [PaneDepth] ;is Y still in bounds?
jbe pw_exit2
mov al,byte ptr [PaneWidth] ;the write ended at the lower right
mov ah,byte ptr [PaneDepth] ;boundary of the Pane.
pw_exit2:
ret
PaneWrite endp
;------------------
ScrollPane proc near
; Scrolls the current pane up one line - Call only after defining Pane parms
; Entry: None
; Return: None
cld
push ds
push es
push si
push di
push dx
push cx
push ax
mov es,WWBuffSeg ;Set up registers for the movsw loops
mov di,[PaneOff]
mov si,di
add si,[TargetIncr]
mov cx,[PaneDepth]
dec cx ;since we are moving n-1 rows, maximum
js sp_exit
jz sp_exit ;Exit if counter negative or zero
sp_loop:
push cx
push si
push di
mov cx,[PaneWidth]
push ds
mov ds,WWBuffSeg ;Set up registers for the movsw loops
rep movsw
pop ds
pop di ;Restore the indices
pop si
pop cx
mov ax,[TargetIncr]
add si,ax ;Increment the indices by the offset in Window buffer
add di,ax
loop sp_loop
sp_exit:
mov al,32 ;Blank the bottom line, keeping attribute
mov cx,[PaneWidth]
sp_blank_line:
stosb
inc di
loop sp_blank_line
pop ax ;Restore registers of interest and return
pop cx
pop dx
pop di
pop si
pop es
pop ds
ret
ScrollPane endp
;------------------
PutScreen proc near
; Writes the screen from work area to video page 0
; Entry: None
; Return: None
cld
test byte [SnowProne],1
jz ps1
call VerticalPause ;Wait for next vertical retrace
ps1:
xor di,di
call GetVidSeg
cmp dx,0B800h
je ps1a
mov ax,[SegB000]
jmp short ps1b
ps1a:
mov ax,[SegB800]
ps1b:
mov es,ax
mov al,[ScreenLines] ;Set up counter
mov bl,80
mul bl
mov cx,ax ;Words to move
push ds ;Set source - the video work area
lds si,[FrontBuffer]
rep movsw
pop ds
ret
PutScreen endp
;------------------
PutBackBuffer proc near
; Writes the BackBuffer to video work area
; Entry: None
; Return: None
cld
mov al,[ScreenLines] ;Set up counter
mov bl,80
mul bl
mov cx,ax ;Words to move
les di,[FrontBuffer]
push ds
lds si,[Backbuffer]
rep movsw
pop ds
ret
PutBackBuffer endp
;------------------
RestoreTopBot proc near
; Restores top and bottom lines from BackBuffer to screen work area,
; according to external parameters BBTop and BBBot
; Entry: dx:ax = pointer to target screen work area
; Return: none
cmp [BBTop],0
je NoTopLines
push dx ;Save target pointer
push ax
mov es,dx
mov di,ax
mov si,word ptr [BackBuffer]
mov al,[BBTop] ;Calculate number of words to move
mov bl,80
mul bl
mov cx,ax
push ds
mov ds,word ptr [BackBuffer+2]
rep
movsw
pop ds
pop ax
pop dx
NoTopLines:
cmp [BBBot],0
je NoBotLines
mov es,dx
mov di,ax
mov si,word ptr [BackBuffer]
mov al,[BBBot] ;Calculate number of words to move
mov bl,80
mul bl
mov cx,ax
mov al,[ScreenLines] ;Calculate offset of first word to move
sub al,[BBBot]
mov bl,160
mul bl
add si,ax ;Win72 incorrectly had these 2 steps as sub
add di,ax
push ds
mov ds,word ptr [BackBuffer+2]
rep
movsw
pop ds
NoBotLines:
ret
RestoreTopBot endp
;------------------
GetVidSeg proc near
; Finds segment of video page 0 and work area
; Entry: None
; Return: Dx=VidSeg
int 11h ;Get system configuration
mov dx,0B800h ;VidSeg if color card
and al,30h ;If mono card
cmp al,30h
jne gvs1
mov dx,0B000h ;Mono VidSeg
gvs1:
ret
GetVidSeg endp
;------------------
VerticalPause proc near
; Pauses until vertical retrace
; Entry: None
; Return: None
call GetVidSeg
mov bx,dx ;Video segment - If mono, looks at different port
vp0:
mov dx,3DAh ;VGA Input Status #1 for color
cmp bx,0B800h
je vp1
mov dx,3BAh
vp1:
in al,dx
test al,8
jz vp0 ;Hold up if VR bit not set
ret
VerticalPause endp
;------------------
FillVideo proc far
; Stuffs a buffer with a 2-byte sequence
; Entry: None -- BP set up for the EQU references
; Return: None
cld
push bp ;Save BP
mov bp,sp ;Set up stack frame
push ds ;Save DS
les di,FVBuffer
mov cx,FVLen
mov ax,FVData
rep stosw
pop ds ;Restore DS
mov sp,bp ;Restore SP -- Yo, Boboli Pizza - Thissa
;uselessa steppa, man! You gotta keep the
;stack right, or you'll screw up ds, and if
;you've been cool and not corrupted it,
;sp's already same as bp!
pop bp ;Restore BP
ret FVAdjust
FillVideo ENDP
; ----------------
Different proc far
; Different compares MCByteCount bytes in the arrays pointed to
; by MCSource and MCTarget, and returns the result of the comparison
; in the flags register.
cld
push bp ;Save BP
mov bp,sp ;Set up stack frame
push ds ;Save DS
mov cx,MCByteCount ;load the byte count
les di,MCTarget ;load the target pointer is es:di
lds si,MCSource ;and the source is ds:si
repe cmpsb ;compare bytewise while equal
je MCSame
mov ax,1
jmp short MCOut
MCSame:
xor ax,ax
MCOut:
pop ds
pop bp
ret MCAdjust
Different endp
; ----------------
A_________ proc far
; Internal use only
cld
push bp ;Save BP
mov bp,sp ;Set up stack frame
push ds ;Save DS
pop ds
pop bp
ret
A_________ endp
ENDS CODE
END